package boardgamer.common;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Contains a collection of objects that can be reused. When finished using an
 * object, call {@link #store} to keep the object from being garbage collected.
 *
 * @author garysoed
 */
public class ObjectPool<T> {

  private final Provider<T> provider;
  private final ConcurrentLinkedQueue<T> unusedObjects;

  public ObjectPool(Provider<T> provider) {
    this.provider = checkNotNull(provider, "provider");
    this.unusedObjects = new ConcurrentLinkedQueue<T>();
  }

  /**
   * Returns a stored object, or a new instance as defined by
   * {@link Provider#newInstance} if there are no objects stored.
   */
  public T get() {
    if (unusedObjects.isEmpty()) {
      return provider.newInstance();
    } else {
      return unusedObjects.remove();
    }
  }

  /**
   * Stores an object to be reused later.
   */
  public void store(T object) {
    unusedObjects.add(object);
  }

  public static interface Provider<C> {
    C newInstance();
  }
}
